/**
 * 挖掘建模控制类
 */
function MineModelingController() {
    var modelTabs = $('#tempo-mine-model-tabs');
    var addPageBtn = modelTabs.find('.tempo-mine-addpage');
    var addPagePLBtn = modelTabs.find('.tempo-mine-addpage-pl');
    var mineLeftBtn = modelTabs.find('.tempo-mine-cont-leftbtn');
    var mineRightBtn = modelTabs.find('.tempo-mine-cont-rightbtn');
    var expandPageBtn = modelTabs.find('.tempo-mine-expandBtn > input');
    var modelTabContParent = modelTabs.find('.tempo-mine-cont');
    var tabContainer = modelTabs.find('.tempo-mine-tab');
    var modelTabCont = modelTabs.find('.tempo-mine-tab-cont');
    modelTabCont.addClass("model-selected");
    var boardContainer = $('#tempo-mine-designer');
    var isK8sCluster = false;
    var isk8sLocal = false;
    // 自定义布局的数据
    var customLayout = { useSign: false, data: []}

    //当前分析主题ID
    var analyseId = window[constant.ANALYSE_ID];

    var resizeSheetPager = function () {
        var width = modelTabs.width();
        addPageWidth = addPageBtn.outerWidth();
        addPagePLWidth = addPagePLBtn.outerWidth();
        expandWidth = expandPageBtn.parent().outerWidth();
        modelTabContParent.width(width);
        var lrWidth = modelTabs.find('.tempo-mine-btn-tab').outerWidth();
        tabContainer.outerWidth(width - lrWidth);
        padding = modelTabContParent.outerWidth(true) - modelTabContParent.outerWidth();
        modelTabContParent.outerWidth(width - expandWidth - padding);
    }

    /**
     * 加载当前分析主题下的所有流程信息
     */
    var loadAnalyseThemeAll = function () {
        $.ajax({
            url: contextPath + "/api/ai/mine/loadAllAnalyseInfo",
            data: {
                analyseId: analyseId
            },
            dataType: 'json',
            type: 'post',
            success: function (result) {
                renderPager(result);
            }
        })
    }
    var addChangeMarkToModelTabCont = function () {
        var tabNav = modelTabCont ? modelTabCont : $('#tempo-mine-model-tabs').find('.tempo-story-tab-cont');
        tabNav.find("span.tempo-mine-tab-curSelect").each(function (index, ele) {
            var ui = $(ele);
            if (!ui.find("label").hasClass('tempo-mine-tab-change')) {
                ui.find("label").addClass('tempo-mine-tab-change');
            }
            return;
        });
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        var curMainId = analyseStatus.getMainId();
        var page = analyseStatus.getFlowPanel(curMainId);
        if (page && page.panel) {
            page.panel.find('.tempo-mine-save').addClass('tempo-ui-blue');
            page.panel.find('.tempo-mine-save').removeClass('tempo-ui-icon-no-mutual');
            page.panel.find('.tempo-mine-save').css("cursor", "pointer");
        }
        //移动时触发，判断撤销和重做是否变黑
        Eventbus.trigger('enableUndoRedoButton.mineToolbar');
    }
    var removeChangeMark = function (id) {
        var tabNav = modelTabCont ? modelTabCont : $('#tempo-mine-model-tabs').find('.tempo-story-tab-cont');
        tabNav.find("span").each(function (index, ele) {
            var ui = $(ele);
            var spanId = ui.attr('linkid');
            if (spanId == id) {
                ui.find("label").removeClass('tempo-mine-tab-change');
            }
        });
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        var curMainId = analyseStatus.getMainId();
        var page = analyseStatus.getFlowPanel(curMainId);
        if (page && page.panel) {
            page.panel.find('.tempo-mine-save').removeClass('tempo-ui-blue');
            page.panel.find('.tempo-mine-save').addClass('tempo-ui-icon-no-mutual');
            page.panel.find('.tempo-mine-save').css("cursor", "default");
        }
    }
    /**
     * 初始化页签信息
     */
    var renderPager = function (list) {
        pageBtnClick();
        modelTabCont.on("dblclick", "span", function (e) {
            e.stopPropagation();
            //if(!e.ctrlKey) return;
            var span = $(this),
                linkId = span.attr("linkId");
            pagerDblclick(span);
        }).on("click", "span", pagerClick);
        modelTabCont.on("click", 'span>i', pageContextMenu).on("dblclick", function (e) {
            e.stopPropagation();
        });

        modelTabCont.on("mouseenter", 'span', function () {
            if ($(this).hasClass('tempo-mine-tab-curSelect')) {
                var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
                var curid = analyseStatus.getMainId();
                var curType = analyseStatus.getType();
                if ('modeling' == curType) {
                    $(this).find('i').css("opacity", 1);
                } else if ('viewing' == curType) {
                    $(this).find('i').css("opacity", 0);
                }
            }
        }).on("mouseleave", 'span', function () {
            $(this).find('i').css("opacity", 0);
        });

        var selectId = window.location.hash;
        var selectIndex = 0;
        for (var i = 0; i < list.length; i++) {
            if (selectId && selectId.indexOf(list[i].id) > -1) {
                selectIndex = i;
                break;
            }
        }
        for (var i = 0; i < list.length; i++) {
            addSheet(list[i], i == selectIndex);
        }
        resizeSheetPager();
        rollpage.resize();
        rollpage.roll();
    }

    /**
     * 渲染故事页签
     */
    var addSheet = function (item, selected) {
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        analyseStatus.addSheet(item.id, item);
        var span = $("<span/>", {
            linkId: item.id
        }).data("tempo-storypage", item);
        //添加面板下方流程名称旁边的图标
        var flowImgUrl = contextPath + "/css/images/flow_icon.png";
        //用来区分管道流程还是普通流程
        var flowType = "flow";
        if (item.type == "plflow") {
            flowImgUrl = contextPath + "/css/images/flow_pl_icon.png";
            flowType = "plflow";
        }
        var flowImg = $("<img/>").addClass("tempo-mine-flow-image-icon");
        flowImg.attr("src", flowImgUrl);
        flowImg.attr("flowType", flowType);
        span.append(flowImg);
        var label = $("<label/>", {
            title: item.name,
            text: item.name
        }).appendTo(span);
        var i = $("<i/>", {
            "class": "ui-icon tempo-ui-icon tempo-mine-button tempo-ui-icon-setting"
        }).appendTo(span);
        span.appendTo(modelTabCont);
        if (selected === true) {
            span.trigger("click", true);
        }
        pagerDragDrop(span);
        return span;
    }

    /**
     * 切换sheet页，加载并初始化面板
     */
    var pagerClick = function (event, first, id) {
        var linkId = undefined, t = undefined;
        if (id) {
            linkId = id;
        } else {
            t = $(this);
            linkId = t.attr("linkId");
        }
        var urlHash = window.location.hash;
        if (urlHash.indexOf("_") > -1) {
            var splitArr = urlHash.split("_");
            //处理安全扫描问题Cross-Site Scripting: DOM
            if (splitArr[1] == "modeling") {
                window.location.hash = linkId + "_" + "modeling";
            } else if (splitArr[1] == "viewing") {
                window.location.hash = linkId + "_" + "viewing";
            }
        } else {
            window.location.hash = linkId;
        }
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        var curid = analyseStatus.getMainId();

        //切换页签样式
        modelTabContParent.find(".tempo-mine-tab-curSelect")
            .removeClass("tempo-mine-tab-curSelect");
        if (t) {
            t.addClass("tempo-mine-tab-curSelect");
        }

        if ('modeling' == analyseStatus.getType()) {
            var curBoardId = linkId;
            //加载页面
            loadBoard(curBoardId);
            if (curid) {
                Eventbus.trigger('refreshModelLogger.mine');
            }
            var page = analyseStatus.getFlowPanel(curBoardId);
            if (page) {
                var board = page.panel.flowpanel('getBoard');
                var name = board.attr('_widgetname');
                if (name) board[name]('clearSelect');
                if ($("#tempo-mine-element-library-option").hasClass("tempo-mine-library-manager-option-select")) {
                    Eventbus.trigger('clear_help_content.mine');
                }
            }
            // 手动点击页签时，则显示按钮
            if ('modeling' == analyseStatus.getType() && event.pageX && event.pageY) {
                $(this).find('i').css("opacity", 1);
            }
        } else if ('viewing' == analyseStatus.getType()) {
            if (!curid || curid != linkId) {
                Eventbus.trigger("switchToViewing.mine", linkId);
            }
        }
        //切换流程页签，要素库和模型库需要做特殊处理
        refreshPageForPagerClick();
        return true;
    }

    /**
     * 切换流程页签，要素库和模型库需要做特殊处理
     */
    var refreshPageForPagerClick = function () {
        //获取当前流程类型
        var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
        //选择全部还是分布式
        var selector = $('.distributeSwitch-select').val();
        if (selector == "all") {
            Eventbus.triggerHandler("mine.library-isDistribute", false, "", flowType);
        } else {
            Eventbus.triggerHandler("mine.library-isDistribute", true, "", flowType);
        }
        if (flowType == "plflow") {
            //管道流程不展示导入PMML模型按钮
            $("#tempo-mine-alg-type-select-button").width(198);
        } else {
            $("#tempo-mine-alg-type-select-button").width(162);
        }
        //如果选中的是模型库，则每次选中的流程都要刷新模型库
        var id = $(".tempo-mine-library-manager-option-select").attr("id");
        if (id == "tempo-mine-model-library-option") {
            initModelLibrary(isK8sCluster, isk8sLocal);
        }
    }

    /**
     * sheet页签双击事件
     */
    var pagerDblclick = function (linkEl) {
        var t = linkEl, data = t.data("tempoStorypage"), label = t
            .find("label");
        //api主题预览模式下,不进行操作
        if (window.apiPreview) {
            return false;
        }
        label.empty();
        var input = $("<input/>", {
            value: data.name,
            "class": 'tempo-mine-pager-input'
        }).appendTo(label).on("click dblclick", function (e) {
            e.stopPropagation();
        }).on("blur", function () {
            var oldFlowName = input.attr('value');
            input.remove();
            var $t = $(this), val = this.value;
            var regex = new RegExp('[\\\\\/"\';:|？?*<> &.]');
            if (regex.test(val)) {
                val = oldFlowName;
                setTimeout(function () {
                    $("<div/>").alert({
                        msg: TempoUtils.locale("mine.flowNameError"),
                        ok: function () {
                        }
                    })
                }, 100);
            }
            if (val == '' || val == data.name) {
                val = data.name;
                label.text(val).attr("title", val);
            } else {
                if (val.length && val.length > 60) {
                    $("<div/>").alert({
                        msg: TempoUtils.locale("mine.flownameValid"),
                        ok: function () {
                            label.text(data.name).attr("title", data.name);
                        }
                    })
                } else {
                    updatePageName(data.id, val, function (result) {
                        if (result) {
                            data.name = val;
                            label.text(val).attr("title", val);
                            $('#fc-' + data.id).flowpanel('updateName', val);
                        } else {
                            var match = val.match(/[0-9]+/g);
                            if (match != null && parseInt(match[0]) > 2147483647) {
                                $("<div/>").alert({
                                    msg: TempoUtils.locale("mine.liuchengmingerror"),
                                    ok: function () {
                                        label.text(data.name).attr("title", data.name);
                                    }
                                })
                            } else {
                                $("<div/>").alert({
                                    msg: TempoUtils.locale("mine.flowNameExist"),
                                    ok: function () {
                                        label.text(data.name).attr("title", data.name);
                                    }
                                })
                            }
                        }
                    });
                }
            }

        }).on("keydown", function (event) {
            if (event.keyCode == 13) {
                $(this).trigger('blur');
            }
        }).focus();

    }

    /**
     * 更新流程名称
     */
    var updatePageName = function (proid, name, callback) {
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + "/api/ai/mine/updateProgressName",
            data: {
                proid: proid,
                name: name
            },
            dataType: 'json',
            type: 'post',
            success: function (result) {
                process.tempoprogressbar("destroy");
                callback(result);
            },
            error: function () {
                process.tempoprogressbar("destroy");
            }
        })
    }

    /**
     * 移除当前sheet页
     */
    var removeSheet = function (linkEl) {

        //选择下一个选中的页签，当前删除的页签不是选中的页签，则不需要跳转
        var next = linkEl.prev();
        if (!next.length) {
            next = linkEl.next();
        }
        if (!linkEl.hasClass('tempo-mine-tab-curSelect')) {
            next = null;
        }
        $("<div/>").confirm({
            msg: TempoUtils.locale("mine.mine_del"),
            ok: function () {
                var id = linkEl.attr("linkId");
                var board = $('#fc-' + id).flowpanel('getBoard');
                var json = board.miningboard("getFlowData");
                if (json != null && json.children != null && json.children.length > 0) {
                    var children = json.children;
                    for (var i = 0; i < children.length; i++) {
                        var childNode = children[i];
                        var eid = childNode.eid;
                        var tt = $('#' + eid);
                        if (tt.length > 0) {
                            tt[tt.attr('_widgetname')]('deleteCache');
                        }
                    }
                }
                var data = linkEl.data("tempo-storypage");
                if (modelTabCont.find("span").length == 1) {
                    $("<div/>").alert(
                        {
                            msg: TempoUtils.locale("mine.lastDelRefuse")
                        });
                    return;
                }

                var process = $("<div/>").tempoprogressbar();
                $.ajax({
                    url: contextPath + "/api/ai/mine/removeProgress",
                    data: {
                        id: id
                    },
                    dataType: 'json',
                    type: 'post',
                    success: function (rs) {
                        if (!rs) {
                            TempoUtils.showTip(TempoUtils.locale("mine.errorDeleteFlow"));
                            return;
                        }
                        linkEl.remove();
                        //removeUserFileUpload(id);
                        try {
                            $("#fc-" + id).flowpanel("destroy").remove();
                        } catch (e) {
                        }
                        if (next && next.length) {
                            next.trigger("click");
                        }
                        rollpage.resize();
                        //重新刷新位置
                        rollpage.roll();
                    },
                    complete: function () {
                        process.tempoprogressbar("destroy");
                    }
                })
            }
        })

    }

    var removeUserFileUpload = function (flowId) {
        $.ajax({
            url: contextPath + "/userFileUpload/deleteByFlowId",
            data: {
                flowId: flowId
            },
            success: function (res) {
            }
        });
    }

    /**
     * 页签右键菜单
     */
    var pageContextMenu = function (e) {
        if ($(this).css("opacity") == 0) {
            return;
        }
        var contextmenu = null,
            menus = [{
                text: TempoUtils.locale("mine.mine_del"),
                id: 'delete',
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-delete'
            }, {
                text: TempoUtils.locale("mine.mine_rename"),
                id: 'rename',
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-rename'
            }, {
                text: TempoUtils.locale("mine.mine_copy"),
                id: 'copy',
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-copy'
            }, {
                text: TempoUtils.locale("mine.mine_import"),
                id: 'import',
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-import'
            }, {
                text: TempoUtils.locale("mine.mine_export"),
                id: 'export',
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-export'
            }];

        /**
         * 删除数组项
         */
        var removeArrayItem = function (arr, itemId) {
            if (!arr || arr.length <= 0) {
                return arr;
            }
            for (var i = 0; i < arr.length; i++) {
                if (arr[i].id == itemId) {
                    arr.splice(i, 1);
                    break;
                }
            }
            return arr;
        }
        //设计端启用限制，不能复制
        if (TempoAuthorityUtils.isDesignerLimited()) {
            menus = removeArrayItem(menus, 'copy');
        }
        pageContextMenu = function (e) {
            e.stopPropagation();
            var span = $(e.currentTarget).closest("span"),
                linkId = span.attr("linkId");

            if (!contextmenu) {
                contextmenu = $("<ul/>").appendTo($("body"))
                    .contextmenu({
                        data: menus,
                        select: function (e, ui) {
                            var id = ui.select.id;
                            switch (id) {
                                case 'delete':
                                    removeSheet(ui.linkEl);
                                    break;
                                case "rename":
                                    pagerDblclick(ui.linkEl);
                                    break;
                                case "copy":
                                    // 在复制流程之前保存当前流程的所有参数
                                    Eventbus.trigger('mineSave.mine');
                                    copySheet(ui.linkEl);
                                    break;
                                case "export":
                                    // 在导出流程之前保存当前流程的所有参数
                                    Eventbus.trigger('mineSave.mine');
                                    exportSheet(ui.linkEl);
                                    break;
                                case "import":
                                    importSheet(ui.linkEl);
                                    break;
                                default:
                                    break;
                            }
                        }
                    })
            }
            var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
            var curMainId = analyseStatus.getMainId();
            if (curMainId != linkId) {
//				contextmenu.contextmenu('disableItem', 'import');
                var page = analyseStatus.getFlowPanel(linkId);
                var board = page.panel.flowpanel('getBoard');
                var json = board.miningboard('getJson');
                if (json.children && json.children.length > 0
                    && json.children.filter(function (child) {
                        return child.nodeType != 'END'
                    }).length > 0) {
                    contextmenu.contextmenu('disableItem', 'import');
                } else {
                    contextmenu.contextmenu('disableItem', 'export');
                }
            } else {
                var page = analyseStatus.getFlowPanel(curMainId)
                if (page) {
                    var board = page.panel.flowpanel('getBoard');
                    var json = board.miningboard('getJson');
                    if (json.children && json.children.length > 0
                        && json.children.filter(function (child) {
                            return child.nodeType != 'END'
                        }).length > 0) {
                        contextmenu.contextmenu('disableItem', 'import');
                    } else {
                        contextmenu.contextmenu('disableItem', 'export');
                    }
                }
            }
            var offset = span[0].getBoundingClientRect();
            var left = offset.right + 150 >= $(window).outerWidth() ? offset.right - 160 : offset.right;
            contextmenu.contextmenu("show", {
                position: {
                    left: left,
                    top: offset.top - contextmenu.height()
                },
                linkEl: span
            });
        }
        pageContextMenu.call(this, e);
    }
    /**
     * 分页拖拽事件
     */
    var pagerDragDrop = function (span) {
        var that = this;
        span.draggable({
            containment: '.tempo-mine-tab-cont',
            scroll: false,
            helper: 'clone',
            zIndex: 10,
            delay: 100,
            distance: 5,
            axis: 'x',
        }).droppable(
            {
                accept: '.tempo-mine-tab-cont>span',
                drop: function (e, ui) {
                    var drag = ui.draggable, $t = $(this), all = $t
                        .parent().find(">span:visible").not(
                            ui.helper);
                    // 如果拖拽的元素在置放元素之前，则将元素放在置放元素之后
                    if (all.index(drag) < all.index($t)) {
                        drag.detach().insertAfter($t);
                        updateIdx(drag.attr("linkId"), $t.attr("linkId"));
                    } else {
                        drag.detach().insertBefore($t);
                        updateIdx(drag.attr("linkId"), drag.prevAll("span:visible:first").attr("linkId"));
                    }
                    //此时还存在helper元素，会导致计算多一个span，故采用延迟resize
                    setTimeout(function () {
                        rollpage.resize();
                        rollpage.roll();
                    }, 100);
                }
            })
    }

    var updateIdx = function (id, preId) {
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + "/api/ai/mine/updatePageIndex",
            data: {
                id: id,
                preId: preId || '-1',
                pid: analyseId
            },
            dataType: 'json',
            type: 'post',
            success: function () {
                process.tempoprogressbar("destroy");
            },
            error: function () {
                process.tempoprogressbar("destroy");
            }
        })
    }
    /**
     * 添加sheet页按钮事件
     */
    var pageBtnClick = function () {
        //新建普通流程
        addPageBtn.on("click", function () {
            Eventbus.trigger('selectButton.mine', 'modeling');
            var item = getNewPageData();
            createAnalyseFlow(item);
        });
        //新建管道流程
        addPagePLBtn.on("click", function () {
            Eventbus.trigger('selectButton.mine', 'modeling');
            var item = getNewPagePLData();
            createAnalyseFlow(item);
        });

        mineLeftBtn.on("click", function () {
            rollpage.roll('left');
        });

        mineRightBtn.on("click", function () {
            rollpage.roll('right');
        });
    }
    var copySheet = function (el) {
        var id = el.attr('linkid');
        var item = getNewPageData();
        //获取当前流程类型
        var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
        if (flowType == "plflow") {
            item = getNewPagePLData();
        }
        item.copyId = id;
        var name = el.find('label').text();
        var names = el.siblings().get().map(function (e) {
            return $(e).find('label').text();
        });
        var index = 1;
        var reg = new RegExp("^(.*)(\\d+)$");
        var r = reg.exec(name);
        var name_ = name;
        if (r && r.length == 3) {
            index = parseInt(r[2]) + 1;
            name_ = r[1];
        }
        while (true) {
            var filter = names.filter(function (e) {
                return e == name_ + index
            });
            if (filter.length) {
                index++;
            } else {
                break;
            }
        }
        item.name = name_ + index;
        setTimeout(function () {
            createAnalyseFlow(item);
        }, 10);
    }

    var exportSheet = function (el) {
        var id = el.attr('linkid');
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + "/api/ai/mine/searchFlowInfo",
            data: {
                id: id
            },
            dataType: 'json',
            type: 'post',
            success: function (result) {
                if (result.length == 0) {
                    $("<div/>").alert(
                        {
                            msg: TempoUtils.locale("mine.baocunliuchengdaoru")
                        });
                } else {
                    TempoUtils.download({data: {id: id}, url: contextPath + '/api/ai/mine/exportSheet'});
                }
//				process.tempoprogressbar("destroy");
            },
            complete: function () {
                process.tempoprogressbar("destroy");
            }
        });


    }

    /**
     * 导入流程，上传文件，返回流程信息
     */
    var importSheet = function (el) {
        var id = el.attr('linkid');
        //获取当前流程类型
        var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
        var form = $("#tempo-mining-import-flow-form");
        //应该导入流程的后缀，默认.tflow
        var flowSuffix = ".tflow";
        if (flowType == "plflow") {
            flowSuffix = ".tpl";
        }
        form.find("#tempo-mining-import-flow-button").attr("accept", flowSuffix);
        form.find('input[name="id"]').val(id);
        form.find('input[name="themeId"]').val(window[constant.ANALYSE_ID]);
        var uploadFileBtn = $("#tempo-mining-import-flow-button");
        uploadFileBtn.unbind("change").bind("change", function (e) {
            importFileSubmit(form, $(this), id, flowType);
            e.target.value = "";
        });
        uploadFileBtn[0].click();
    }

    var importFileSubmit = function (form, uploadFileBtn, flowId, flowType) {
        var file = uploadFileBtn[0].files[0];
        var fileSize = file.size;
        if (fileSize <= 0) {
            $("<div/>").alert({
                msg: "空文件无法导入",
                ok: function () {
                    $("#tempo-mining-import-flow-form")[0].reset();
                }
            });
            return;
        }
        var fileName = file.name;
        //上传文件的后缀
        var uploadSuffix = fileName.substring(fileName.lastIndexOf("."));
        //支持的后缀类型
        var supportSuffixArray = [".tflow", ".tpl", ".zip"];
        if (supportSuffixArray.indexOf(uploadSuffix) == -1) {
            $("<div/>").alert({
                msg: TempoUtils.locale("mine.flow_upload_tip"),
                ok: function () {
                    $("#tempo-mining-import-flow-form")[0].reset();
                }
            });
            return;
        }
        //普通流程无法导入空白的管道流程
        if (fileName.endsWith(".tflow") && flowType == "plflow") {
            $("<div/>").alert({
                msg: "普通流程无法导入空白的管道流程",
                ok: function () {
                    $("#tempo-mining-import-flow-form")[0].reset();
                }
            });
            return;
        }
        var process = $("<div/>").tempoprogressbar();
        form.ajaxSubmit({
            dataType: 'json',
            type: 'post',
            beforeSubmit: function (result) {
                return true;
            },
            success: function (data) {
                if (process) {
                    process.tempoprogressbar("destroy");
                }
                if (data == 'ok') return;
                //JSON.stringify转出来的字符串前面会加上双引号，用此判断
                if (data && JSON.stringify(data).startsWith('"error')) {
                    $("<div/>").alert({
                        msg: JSON.stringify(data).replace("error", ""),
                        ok: function () {
                            $("#tempo-mining-import-flow-form")[0].reset();
                        }
                    });
                    return;
                }
                if (data && data.updateFlowType) {
                    var curSelect = $(".tempo-mine-tab-curSelect").find("img[class='tempo-mine-flow-image-icon']");
                    //更换图标 更换流程类型
                    curSelect.attr("src", contextPath + "/css/images/flow_pl_icon.png").attr("flowtype", "plflow");
                    //更换流程左上角图标
                    $(".navigator-root-icon").addClass("navigator-root-pl-icon").removeClass("navigator-root-icon");
                    //重新加载要素库
                    Eventbus.triggerHandler("mine.library-isDistribute", false, "", data.flowType);
                }
                //前端导入流程后渲染节点
                Eventbus.trigger('importNode.mine', flowId, data);
                //保存流程信息
                Eventbus.trigger('mineSave.mine');
                //如果选中的是模型库，导入流程时要刷新模型库
                var id = $(".tempo-mine-library-manager-option-select").attr("id");
                if (id == "tempo-mine-model-library-option") {
                    initModelLibrary(isK8sCluster, isk8sLocal);
                }
                //导入流程之后删除撤销回退堆栈
                var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
                //获取当前面板id
                var id = analyseStatus.getMainId();
                analyseStatus.removeUndoManager(id);
                //判断导入流程时的撤销和重做变黑
                Eventbus.trigger('enableUndoRedoButton.mineToolbar');
            },
            complete: function (e) {

            },
            error: function (e) {
                process.tempoprogressbar("destroy");
                if (e && e.responseText) {
                    $("<div/>").alert({
                        msg: e.responseText.replace("error", ""),
                        ok: function () {
                            $("#tempo-mining-import-flow-form")[0].reset();
                        }
                    });
                }
            }
        });
    }

    /**
     * 导入流程，上传文件，返回流程信息
     */
    var importSheet2 = function (el) {
        var id = el.attr('linkid');
        if (!el.hasClass('tempo-mine-tab-curSelect')) el.click();
        var isStop = false;
        var dialog = $("<div/>").appendTo($("body")).dialog({
            title: TempoUtils.locale("mine.flow_import"),
            height: 170,
            width: 500,
            modal: true,
            draggable: true,
            resizable: false,
            buttons: [{
                text: TempoUtils.locale("mine.import"),
                click: function (e) {
                    if (isStop) return;
                    var form = dialog.find('form');
                    var nameshow = form.find('input[name=nameshow]')
                    var file = nameshow.val();
                    if (file) {
                        var process = $("<div/>").tempoprogressbar();
                        form.ajaxSubmit({
                            dataType: 'json',
                            type: 'post',
                            beforeSubmit: function (result) {
                                isStop = true;
                                return true;
                            },
                            success: function (data) {
                                if (data == 'ok') return;
                                if (data == 'error') {
                                    process.tempoprogressbar("destroy");
                                    TempoUtils.uploadErrorHandler(data);
                                }
                                Eventbus.trigger('importNode.mine', id, data);
                                Eventbus.trigger('mineSave.mine');
                            },
                            complete: function () {
                                dialog.dialog('destroy').remove();
                                process.tempoprogressbar('destroy');
                            },
                            error: function (e) {
                                process.tempoprogressbar("destroy");
                                TempoUtils.uploadErrorHandler(e);
                            }
                        });
                    } else {
                        nameshow.validatebox('doValidate');
                        nameshow.validatebox('showTip');
                    }
                }
            }],
            hide: {
                effect: 'fade',
                duration: 300
            },
            open: function () {
                var ui = $(this);
                var form = $('<form>').appendTo(ui)
                    .attr('enctype', 'multipart/form-data')
                    .attr('method', 'post')
                    .attr("action", contextPath + '/api/ai/mine/importSheet');
                $('<input name="id" type="hidden">').appendTo(form).val(id);
                $('<input name="themeId" type="hidden">').appendTo(form).val(window[constant.ANALYSE_ID]);
                $('<label>').text(TempoUtils.locale("mine.flow_file")).appendTo(form);
                var filenameText = $('<input name="nameshow">').appendTo(form)
                    .validatebox({
                        readonly: true,
                        width: 300,
                        height: 28,
                        required: true,
                        tip: TempoUtils.locale("mine.flow_upload_tip")
                    })
                    .css('margin', '2px 10px 0px 10px');
                var wrapper = $('<a href="javascript:void(0)" >')
                    .appendTo(form)
                    .text(TempoUtils.locale("mine.flow_choose"))
                    .css({
                        'margin-bottom': '3px',
                        'overflow': 'hidden',
                        'cursor': 'pointer'
                    })
                    .button({
                        click: function (e) {
                            var $thisBtn = $(this);
                            $thisBtn.button("option", "disabled", true);
                            setTimeout(function () {
                                $thisBtn.button("option", "disabled", false);
                            }, 3000);
                        }
                    });
                var fileInput = $('<input class="uploadinput">')
                    .attr('type', 'file')
                    .attr('name', 'file')
                    .attr('accept', '.tflow')
                    .css({
                        opacity: 0,
                        position: 'absolute',
                        top: 0,
                        right: 0,
                        "font-size": '100px'
                    })
                    .appendTo(wrapper);
                fileInput.bind("change", function (e) {
                    var file = fileInput[0].files[0];
                    if (file && (file.name.endsWith('.tflow') || file.name.endsWith('.zip'))) {
                        filenameText.validatebox('setValue', file.name)
                    } else {
                        filenameText.val('');
                    }
                    filenameText.validatebox('doValidate');
                });
            },
            close: function () {
                $(this).dialog("destroy").remove();
            }
        });
    }
    /**
     * 滚动页面
     */
    var rollpage = (function () {
        var unit = 121;
        //距离右边的距离
        var right = 81.5;
        return {
            roll: function (direction) {
                var width = tabContainer.width();
                var childWidth = modelTabCont.width();
                var childLeft = modelTabCont.css('left').replace('px', '').replace('auto', '0');
                childLeft = Number(childLeft);
                var childRight = modelTabCont.css('right').replace('px', '').replace('auto', '0');
                childRight = Number(childRight);
                if ('right' == direction) {
                    if (childWidth + childLeft - 41 > width && childLeft == 0) {
                        modelTabCont.css('left', childLeft - unit - 41);
                    } else if (childWidth + childLeft - 40 >= width) {
                        modelTabCont.css('left', childLeft - unit);
                    }
                    if (window.screen.width == 1366 && childWidth + childLeft > width) {
                        modelTabCont.css('left', childLeft - unit);
                    }
                    if (childRight > 0 && childRight < right) {
                        childLeft = Number(modelTabCont.css('left').replace('px', '').replace('auto', '0'));
                        modelTabCont.css('left', childLeft - (right - childRight));
                    }
                } else if ('left' == direction) {
                    if (childLeft + unit <= 0) {
                        modelTabCont.css('left', childLeft + unit);
                    } else {
                        modelTabCont.css('left', 0);
                    }
                } else {
                    var spans = modelTabCont.find('>span');
                    spans.each(function (i, e) {
                        if ($(this).hasClass('tempo-mine-tab-curSelect')) {
                            var position = (i + 1) * unit + childLeft;
                            if (position <= unit * 1) {
                                modelTabCont.css('left', i * unit * -1);
                            } else if (position >= width - 82) {
                                modelTabCont.css('left', -((i + 1) * unit - width + 82));
                            } else {
                                if ((i + 1) * unit > width - 82) {
                                    modelTabCont.css('left', -((i + 1) * unit - width + 82));
                                } else if (spans.length * unit > width - 40) {
                                    var u = Math.ceil((width - 40) / unit);
                                    modelTabCont.css('left', -(u * unit - width + 40));
                                } else {
                                    modelTabCont.css('left', 0);
                                }
                            }
                            return false;
                        }
                    });
                }
            },
            resize: function () {
                var width = modelTabs.width();
                addPageWidth = addPageBtn.outerWidth();
                addPagePLWidth = addPagePLBtn.outerWidth();
                var lrWidth = modelTabs.find('.tempo-mine-btn-tab').outerWidth();
                //计算所有页签的宽度
                var total = modelTabCont.find('>span')
                    .get()
                    .map(function (e) {
                        return $(e).outerWidth();
                    })
                    .reduce(function (a, b) {
                        return a + b;
                    });
                modelTabCont.width(total + 0.5);
                //调整增加按钮的位置
                if (total + addPageWidth + addPagePLWidth < width - lrWidth) {
                    addPageBtn.css('left', total);
                    addPagePLBtn.css('left', total + 41);
                } else {
                    addPageBtn.css('left', '').css('right', 0);
                    addPageBtn.css('margin-right', 41);
                    addPagePLBtn.css('left', '').css('right', 0);
                }
                var left = -Number(modelTabCont.css('left').replace('px', ''));
                var actual = total - width;
                if (left > 0 && actual > 0 && left > actual) {
                    modelTabCont.css('left', -actual);
                }
                if (left > 0 && actual < 0) {
                    modelTabCont.css('left', 0);
                }
            }
        }
    })();

    /**
     * 添加普通流程新页面时候要返回的数据
     */
    var getNewPageData = function () {
        return {
            id: TempoUtils.uuid(),
            name: null,
            type: 'flow',
            appId: window[constant.APP_ID],
            parentId: analyseId,
            sort: 0
        }
    }

    /**
     * 添加管道流程新页面时候要返回的数据
     */
    var getNewPagePLData = function () {
        return {
            id: TempoUtils.uuid(),
            name: null,
            type: 'plflow',
            appId: window[constant.APP_ID],
            parentId: analyseId,
            sort: 0
        }
    }

    var saveAs = function (data, content, e) {
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + "/api/ai/mine/saveAs",
            data: {
                resource: JSON.stringify(data),
                copyId: data.copyId || '',
                content: content || ''
            },
            dataType: 'json',
            type: 'post',
            async: false,
            success: function (result) {
                var pager = addSheet(result, true);
                rollpage.resize();
                rollpage.roll('to', pager);
                //另存为后执行
                if (e == true) {
                    var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
                    var id = analyseStatus.getMainId();
                    var page = analyseStatus.getFlowPanel(id);
                    if (!page.panel.flowpanel('isReady')) {
                        $("<div/>").alert({
                            msg: TempoUtils.locale("mine.taskRunningError"),
                            title: TempoUtils.locale("mine.runtask")
                        });
                        return;
                    }
                    setTimeout(function () {
                        Eventbus.trigger('startupFromBar.mine');
                    }, 100);
                }
            },
            complete: function () {
                process.tempoprogressbar("destroy");
            },
            error: function () {
                $("<div/>").alert({
                    msg: TempoUtils.locale("mine.liuchengmingrequesterror"),
                    title: TempoUtils.locale("mine.prompt")
                })
            }
        })
    }
    Eventbus.one("mine.saveAs", saveAs);
    /**
     * 新增一个流程
     */
    var createAnalyseFlow = function (data) {
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + "/api/ai/mine/createAnalyseFlow",
            data: {
                resource: JSON.stringify(data),
                copyId: data.copyId || ''
            },
            dataType: 'json',
            type: 'post',
            async: false,
            success: function (result) {
                var pager = addSheet(result, true);
                rollpage.resize();
                rollpage.roll('to', pager);
            },
            complete: function () {
                process.tempoprogressbar("destroy");
            },
            error: function () {
                $("<div/>").alert({
                    msg: TempoUtils.locale("mine.liuchengmingrequesterror"),
                    title: TempoUtils.locale("mine.prompt")
                })
            }
        })
    }

    var loadBoard = (function () {
        /**
         * boardId 面板id
         * clear 是否清理缓存
         */
        return function (boardId, clear) {
            var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
            var curMainId = analyseStatus.getMainId();
            var page = analyseStatus.getFlowPanel(curMainId);
            //隐藏当前显示的面板
            if (page) {
                //隐藏前先切换回最外层面板，防止缓存数据导致再次切换回去面板和数据对应不上（66063）
                //67898 子流程avigator-path-text包含多个 仅子流程时触发
                if (page.panel.find(".navigator-path-text").length > 1) {
                    $(page.panel.find(".navigator-path-text")[0]).trigger("click");
                }
                page.panel.hide();
            }
            curMainId = boardId;
            page = analyseStatus.getFlowPanel(curMainId);
            analyseStatus.setMainId(curMainId);
            //如果存在当前面板，则显示当前面板
            if (page && clear !== true) {
                page.panel.show();
                //初始化洞察设置，加载时已经渲染，重新切换回来之后需要根据新的页面重新设置值
                Eventbus.trigger("initinsight.mine");
                return;
            }
            if (!page) {
                var panel = $('<div/>').appendTo(boardContainer);
                panel.flowpanel({
                    id: curMainId,
                    analyseId: analyseId,
                    hideLogger: window.apiPreview
                })
                page = {
                    panel: panel,
                    flowId: curMainId
                };
                //缓存10个面板，当打开多于10个时，则先缓存，后删除最先进入的
                var oldId = analyseStatus.addFlowPanel(curMainId, page);
                if (oldId) {
                    var oldPage = analyseStatus.getFlowPanel(oldId);
                    if (oldPage) {
                        oldPage.panel.flowpanel('destroy');
                        analyseStatus.removeFlowPanel(oldPage.flowId);
                        oldPage.panel.remove();
                    }
                }
            }
            if (window.apiPreview) {
                $('.tempo-mine-board-headbar .navigator-buttons').hide();
            }
            //加载面板对应js并进行渲染
            $m.loadScript(page.panel.show(), [contextPath + "/mine/modeling/js/modeling-designer.js"],
                {
                    id: curMainId,
                    panel: page.panel,
                    isAdd: false,
                    //加载完之后回调函数
                    callback: function () {
                        //设置当前场景之后，回填当前场景的工具条选项
                    }
                }, page.panel.flowpanel('getPanelId'));
            //设置画板的尺寸状态
        }
    })();
    Eventbus.one("mining_board_load.mine", loadBoard);
    //加载要素库节点
    var loadElementLibrary = function (loaded) {
        // 获取系统布局数据
        $.ajax({
            url: contextPath + "/api/ai/mine/getLocale",
            dataType: 'json',
            type: 'get',
            async: false,
            success: function (data) {
                if (data.locale == "en_US") {
                    configLocale("mine_load_data_en_US", null, loaded);
                } else if (data.locale == "zh_CN") {
                    configLocale("mine_load_data_zh_CN", null, loaded);
                }
            }
        });
    }
    //根据国际化类型加载相应国际化文件
    var configLocale = function (target, version, loaded) {
        TempoMineUtils.loadCacheNode(target, function (data) {
            loadCallBack(data, loaded);
        })
    }

    //获取常用算子列表
    var getCollectOperators = function () {
        var collectOperatorList = [];
        $.ajax({
            url: contextPath + '/api/ai/operator/collect/get-list',
            type: 'POST',
            async: false,
            success: function (data) {
                collectOperatorList = data;
            }
        });
        return collectOperatorList;
    }

    //抽取/mine/load的回调函数
    var loadCallBack = function (data, loaded) {
        if (typeof data.alg == "string") {
            data.alg = JSON.parse(data.alg);
            data.i18ndict = JSON.parse(data.i18ndict);
        }
        //获取常用算子列表
        var collectOperatorList = getCollectOperators();
        var alg = data.alg;
        //将获取的所有算法节点保存到页面window对象中
        TempoMineUtils.saveAllAlgorithmNodeInfoToWindow(alg);
        //存储常用算子
        for (var i in collectOperatorList) {
            var nodeType = collectOperatorList[i].nodeType;
            var nodeId = collectOperatorList[i].nodeId;
            //这里存储collectId用于删除常用算子操作
            var collectId = collectOperatorList[i].id;
            //有可能对应的算子不存在，这里需要判断一下
            var node = window[nodeType][nodeId];
            if (node != undefined && (String(node.visible) !== "false" || String(node.isShow) !== "false")) {
                window[window.constant.DATAMINE_COMMONOPER][nodeId] = TempoUtils.clone(window[nodeType][nodeId]);
                window[window.constant.DATAMINE_COMMONOPER][nodeId].isGroup = true;
                window[window.constant.DATAMINE_COMMONOPER][nodeId].collectId = collectId;
                //用于校验是否已收藏未收藏
                //只有收藏了的算子才有ifCollect和collectId属性
                window[nodeType][nodeId].ifCollect = true;
                window[nodeType][nodeId].collectId = collectId;
            }
        }
        //将国际化字典保存
        var i18ns = data[window.constant.I18NDICT];
        for (var i in i18ns) {
            TempoUtils.locale(i, i18ns[i]);
        }

        var systemLayoutElementNodes = {};
        // 系统布局数据
        $.each(Object.keys(alg), function (firstLevelIndex, firstLevelValue) {
            // 常用算子不需要放进去
            if (firstLevelValue != "dm_commonoper") {
                // $.extend(elementNodes, alg[firstLevelValue]);
                $.each(Object.keys(alg[firstLevelValue]), function (secondLevelIndex, secondLevelValue) {
                    systemLayoutElementNodes[secondLevelValue] = alg[firstLevelValue][secondLevelValue];
                    // 将节点信息，存储到window[window.constant.MNODES]中，面板需要用
                    window[window.constant.MNODES][secondLevelValue] = alg[firstLevelValue][secondLevelValue];
                });
            }
        });

        // 处理自定义算法不显示的节点
        //查询需要显示的节点集合
        $.ajax({
            url: contextPath + "/api/ai/nodemgmt/list-visible-node",
            dataType: 'json',
            type: 'post',
            // 需要同步
            async: false,
            success: function (res) {
                var needShowNode = res.data;
                // 过滤自定义算法不要的节点
                Object.keys(alg["user_defined"]).forEach(function (value) {
                    if (needShowNode.indexOf(value) == -1) {
                        delete alg["user_defined"][value];
                        delete systemLayoutElementNodes[value];
                        delete  window[window.constant.DATAMINE_COMMONOPER][value];
                        // modufy limy 2023-02-28 自定义算子在取消发布后，在设计区也要可以使用，所以不能删除，只能隐藏
                        var currentAlgNode =  window[window.constant.MNODES][value];
                        if (currentAlgNode) {
                            currentAlgNode.visible = false;
                        }
                    }
                });
            }
        });

        // 判断节点是否隐藏
        isK8sCluster = data.isK8sCluster;
        isk8sLocal = data.isK8sLocal;
        // 对所有算子进行显示和隐藏，除了常用算子
        showOrHideNode(data.isYarn, data.isK8sCluster, data.isOpenHadoop, data.isK8sLocal, systemLayoutElementNodes);
        // 对常用算子进行显示和隐藏
        showOrHideNode(data.isYarn, data.isK8sCluster, data.isOpenHadoop, data.isK8sLocal, window[window.constant.DATAMINE_COMMONOPER]);

        // 判断是否打开自定义布局
        $.ajax({
            url: contextPath + "/api/ai/nodemgmt/general/custom-layout/get-value?key=tempo.ai.node.open-custom-layout",
            dataType: 'json',
            type: 'get',
            // 需要同步
            async: false,
            success: function (res) {
                if (res.success) {
                    customLayout.useSign = res.data;
                } else {
                    customLayout.useSign = false;
                }
            }
        });

        // 更新自定义布局节点数据
        if (customLayout.useSign) {
            // 获取自定义布局数据，并添加常用算子数据
            getCustomLayout();
            // 如果使用自定义布局数据
            customLayout.data.forEach(function (firstLevelValue) {
                // 跳过常用算子
                if (firstLevelValue === "dm_commonoper") {
                    return;
                }
                // 第一层级并列的没有节点
                // 如果有第二层级
                if (firstLevelValue.children) {
                    // 涉及到删除数据，采用for循环，无法使用forEach
                    var firstLevelValueLen = firstLevelValue.children.length;
                    for (var i=firstLevelValueLen-1; i>=0; i--) {
                        var secondLevelValue = firstLevelValue.children[i];
                        // 如果是节点
                        if (secondLevelValue.errmType == 2) {
                            // 从系统节点中拿去最新的数据
                            var nodeInfo = systemLayoutElementNodes[secondLevelValue.errmId];
                            // 如果节点信息存在，并且不是隐藏的
                            if (nodeInfo) {
                                // 如果是隐藏的节点，需要删除
                                if (String(nodeInfo.isShow) === "false" || String(nodeInfo.visible) === "false") {
                                    firstLevelValue.children.splice(i, 1);
                                } else {
                                    // 将数据替换为最新的
                                    Object.keys(nodeInfo).forEach(function (key) {
                                        secondLevelValue[key] = nodeInfo[key];
                                        // 更新名称，后期自定义方法可能要用到
                                        if (key === "name") {
                                            secondLevelValue.errmName = nodeInfo[key];
                                        }
                                    });
                                }
                            } else {
                                // 如果节点信息不存在，需要删除
                                firstLevelValue.children.splice(i, 1);
                            }
                        }
                        // 如果有第三层级，节点
                        if (secondLevelValue.children) {
                            var secondLevelValueLen = secondLevelValue.children.length;
                            for (var j=secondLevelValueLen-1; j>=0; j--) {
                                var thirdNodeValue = secondLevelValue.children[j];
                                // 如果是节点
                                if (thirdNodeValue.errmType == 2) {
                                    // 从系统节点中拿去最新的数据
                                    var nodeInfo = systemLayoutElementNodes[thirdNodeValue.errmId];
                                    // 如果节点信息存在，并且不是隐藏的
                                    if (nodeInfo) {
                                        // 如果是隐藏的节点，需要删除
                                        if (String(nodeInfo.isShow) === "false" || String(nodeInfo.visible) === "false") {
                                            secondLevelValue.children.splice(j, 1);
                                        } else {
                                            // 将数据替换为最新的
                                            Object.keys(nodeInfo).forEach(function (key) {
                                                thirdNodeValue[key] = nodeInfo[key];
                                                // 更新名称，后期自定义方法可能要用到
                                                if (key === "name") {
                                                    thirdNodeValue.errmName = nodeInfo[key];
                                                }
                                            });
                                        }
                                    } else {
                                        // 如果节点信息不存在，需要删除
                                        secondLevelValue.children.splice(j, 1);
                                    }
                                }
                            };
                        }
                    };
                }
            });

            // 存储自定义布局节点id
            var customNodeDataId = [];
            // 数据的名称需要加上(1)， 例如，数据管理(11)
            // 添加统计节点个数
            var customLayoutDataLen = customLayout.data.length;
            for (var i=customLayoutDataLen -1; i>=0; i--) {
                var firstLevelValue = customLayout.data[i];
                var total = 0;
                // 第一层级同级中没有节点
                if (firstLevelValue.children) {
                    firstLevelValue.children.forEach(function (secondLevelValue) {
                        // 第二层级的节点
                        if (secondLevelValue.errmType == 2) {
                            total++;
                            customNodeDataId.push(secondLevelValue.errmId);
                        } else {
                            // 第三层级全是节点
                            if (secondLevelValue.children) {
                                var nodeLength = secondLevelValue.children.length;
                                // 修改第二层级名称
                                secondLevelValue.errmName += "(" + nodeLength + ")";
                                total += nodeLength;
                                secondLevelValue.children.forEach(function (thirdLevelValue) {
                                    customNodeDataId.push(thirdLevelValue.errmId);
                                });
                            }
                        }
                    });
                }
                firstLevelValue.errmName += "(" + total + ")";
                // 将空层级删除
                if (total == 0) {
                    customLayout.data.splice(i, 1);
                }
            };

            // 添加常用算子
            var commonOperatorChildren = [];
            var commonoperator = TempoUtils.clone(window[window.constant.DATAMINE_COMMONOPER]);
            Object.keys(commonoperator).forEach(function (key, index) {
                // 如果常用算子在自定义布局数据之中
                if (customNodeDataId.indexOf(commonoperator[key].id) != -1 && !(commonoperator[key].visible == false || commonoperator[key].isShow == false) ) {
                    var commonOperatorNode = {
                        errmId: commonoperator[key].id,
                        errmName: commonoperator[key].name,
                        errmType: 2,
                        errmIndex: index,
                        errmParentId: 'commonoperator',
                    };
                    Object.keys(commonoperator[key]).forEach(function (nodeKey) {
                        commonOperatorNode[nodeKey] = commonoperator[key][nodeKey];
                    });
                    commonOperatorChildren.push(commonOperatorNode);
                }
            });
            customLayout.data.unshift( {
                errmId: 'commonoperator',
                errmName: '常用算子',
                errmType: 0,
                errmIndex: 0,
                errmParentId: '',
                elementIconId: '',
                content: 'tempo-ui-icon-mine-common-operators',
                row: 0,
                col: 0,
                children: commonOperatorChildren
            });
        }

        // 要素库要渲染的数据
        var renderData = [];
        if (customLayout.useSign) {
            renderData = customLayout.data;
        } else {
            var result = prepareElementLibrary(data.isYarn, data.isK8sCluster, data.isOpenHadoop, data.isK8sLocal);
            // 对原有的数据添加自定义布局属性，兼容历史
            result.forEach(function (firstLevelValue) {
                firstLevelValue.errmName = firstLevelValue.title;
                firstLevelValue.errmType = firstLevelValue.level || 0;
                // 第一层级有图标
                firstLevelValue.content = firstLevelValue.icon;
                firstLevelValue.row = firstLevelValue.icon.row;
                firstLevelValue.col = firstLevelValue.icon.col;
                if (firstLevelValue.children) {
                    firstLevelValue.children.forEach(function (secondLevelValue) {
                        secondLevelValue.errmName = secondLevelValue.title;
                        // 第二层级有可能是节点，entry是算法入口，有此属性必为节点
                        secondLevelValue.errmType = secondLevelValue.entry ? 2 : 1;
                        if (secondLevelValue.entry) {
                            secondLevelValue.errmId = secondLevelValue.id;
                        }
                        if (secondLevelValue.children) {
                            secondLevelValue.children.forEach(function (thirdNodeValue) {
                                thirdNodeValue.errmId =  thirdNodeValue.id;
                                thirdNodeValue.errmName = thirdNodeValue.title;
                                // 第三层级必然是节点
                                thirdNodeValue.errmType = 2;
                            });
                        }
                    });
                }
            });
            renderData = result;
        }


        initLibrary(renderData);
        //根据当前加载的类型来判断是否进行要素库的初始化
        var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
        Eventbus.one('loadMineElementLibrary.mine', function () {
            initLibrary(renderData);
        });
        Eventbus.one('loadMineModelLibrary.mine', function () {
            initModelLibrary(isK8sCluster, data.isK8sLocal);
        });

        Eventbus.one('importPMMLModel.mine', function () {
            importPMMLModel();
        });

        if (analyseStatus.getType() != 'modeling') {
            $("#tempo-mine-library-container").show();
        } else {
            initLibrary(renderData);
            $("#tempo-mine-library-container").show();
        }
        if (loaded) loaded();

    };

    /**
     * 获取自定义布局数据
     */
    var getCustomLayout = function() {

        // 获取自定义布局数据
        $.ajax({
            url: contextPath + "/api/ai/nodemgmt/general/custom-layout/element-and-icon-data",
            dataType: 'json',
            type: 'get',
            // 需要同步
            async: false,
            success: function (res) {
                if (res.success) {
                    customLayout.data = res.data;
                } else {
                    customLayout.data = [];
                }
            }
        });


    };

    /**
     * 对挖掘模式进行判断，以便是否隐藏相关节点
     * @param isYarn 云模式
     * @param isK8sCluster k8s集群
     * @param isOpenHadoop 开启hadoop
     * @param isK8sLocal k8s本地
     * @param elementNodes 所有节点信息
     */
    var showOrHideNode = function (isYarn, isK8sCluster, isOpenHadoop, isK8sLocal, elementNodes) {
        if (!isYarn) {
            if (elementNodes.readhbase) elementNodes.readhbase.visible = false;
            if (elementNodes.readhive) elementNodes.readhive.visible = false;
            if (elementNodes.readhdfs) elementNodes.readhdfs.visible = false;
            if (elementNodes.writehbase) elementNodes.writehbase.visible = false;
            if (elementNodes.writehive) elementNodes.writehive.visible = false;
            if (elementNodes.writehdfs) elementNodes.writehdfs.visible = false;
            if (elementNodes.tensorflow) elementNodes.tensorflow.visible = false;
            //非集群模式下屏蔽pyspark节点
            if (elementNodes.pyspark) elementNodes.pyspark.visible = false;
        }
        //k8s模式下对接大数据集群时 显示隐藏节点
        if ((isK8sCluster || isK8sLocal) && isOpenHadoop) {
            if (elementNodes.readhbase) elementNodes.readhbase.visible = true;
            if (elementNodes.readhive) elementNodes.readhive.visible = true;
            if (elementNodes.readhdfs) elementNodes.readhdfs.visible = true;
            if (elementNodes.writehbase) elementNodes.writehbase.visible = true;
            if (elementNodes.writehive) elementNodes.writehive.visible = true;
            if (elementNodes.writehdfs) elementNodes.writehdfs.visible = true;
        }
        //如果部署模式是k8s，则屏蔽pySpark、matlab节点
        if (isK8sCluster || isK8sLocal) {
            //k8s模式下 隐藏信号分析下所有节点
            $.each(Object.keys(elementNodes), function (index, value) {
                if (elementNodes[value].type == "dm_signal") {
                    elementNodes[value].visible = false;
                }
            });
            if (elementNodes.pyspark) elementNodes.pyspark.visible = false;
            if (elementNodes.pythonparallelization) elementNodes.pythonparallelization.visible = false;
            if (elementNodes.matlab) elementNodes.matlab.visible = false;
            if (elementNodes.tensorflow) elementNodes.tensorflow.visible = false;
            if (elementNodes.readkafka) elementNodes.readkafka.visible = false;
            if (elementNodes.writekafka) elementNodes.writekafka.visible = false;
            if (elementNodes.readsync) elementNodes.readsync.visible = false;
            if (elementNodes.syncoutput) elementNodes.syncoutput.visible = false;
            if (elementNodes.readdatabankbatch) elementNodes.readdatabankbatch.visible = false;
        }

        //把注释框隐藏掉
        if (elementNodes && elementNodes.commentbox) {
            elementNodes.commentbox.visible = false;
        }
    }

    /*
     * 处理模型数据
     */
    var processModelDatas = function (datas) {
        var categories = ["classification", "regression", "clustering", "association", "timeseries", "comprehensiveevaluation", "textmining", "recommendation", "tensorflow", "pmml"];
        //按时间排序
        var compareFun = function (item1, item2) {
            if (item1.createTime < item2.createTime)
                return 1;
            else if (item1.createTime > item2.createTime) {
                return -1;
            } else {
                return 0;
            }
        }
        var modelInfos = datas.sort(compareFun);
        var newDatas = [];
        var cacheDataMap = {};
        if (modelInfos != null && modelInfos.length > 0) {
            var modelNameMap = new Map();
            var rootNodeMap = new Map();
            for (var i = 0; i < modelInfos.length; i++) {
                var modelInfo = modelInfos[i];
                //把名称进行转义，要不然报错
                modelInfo.name = TempoMineUtils.encodeHTML(modelInfo.name);
                cacheDataMap[modelInfo.id] = modelInfo;
                var description = modelInfo.description;
                if (description == null || $.trim(description).length == 0) {
                    description = JSON.parse(modelInfo.modelInfo).description;
                }
                var desArr = [];
                if ($.isArray(description)) {
                    desArr = description;
                } else {
                    desArr = JSON.parse(description);
                }

                var metadata = [];
                if (desArr.length >= 2) {
                    metadata = desArr[2];
                }
                var metadataStr = TempoMineUtils.metadataToJsonstr(metadata);
                var key = modelInfo.name + "-" + metadataStr;
                // 新的分类方式
                if(modelInfo.modelNameUniqueCode){
                    key = modelInfo.modelNameUniqueCode;
                }

                if (!modelNameMap.get(key)) {
                    var modelInfoObj = JSON.parse(modelInfo.modelInfo);
                    var insightInfo = modelInfoObj.insightInfo || {};
                    var category = insightInfo.producerNodeCategory;
                    var producerNodeTypeId = insightInfo.producerNodeTypeId || modelInfoObj.producerNodeTypeId;
                    //历史兼容
                    if (typeof category != "undefined" && category.length == 0) {
                        if (["tmlda", "vsm"].indexOf(producerNodeTypeId) != -1) {
                            category = "textmining";
                        }
                        if (producerNodeTypeId == "votingclassify") {
                            category = "classification";
                        }
                        if (producerNodeTypeId == "votingreg") {
                            category = "regression";
                        }
                    }
                    if (categories.indexOf(category) == -1) {
                        category = "other";
                    }
                    var rootNode = {
                        children: [],
                        type: 'group',
                        icon: "ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-close",
                        title: modelInfo.name,
                        category: category,
                        id: modelInfo.id,
                        disableMenu: false,
                    };
                    // 默认是创建时间
                    var childTitle= modelInfo.createTime;
                    if(modelInfo.type == "5"){
                        childTitle = modelInfo.modelId.split("_")[1];
                    }
                    var childNode = {
                        title: childTitle,
                        disableMenu: false,
                        libraryType: "modelLibray",
                        icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-unselect'
                    };
                    $.extend(childNode, modelInfo);
                    rootNode.children.push(childNode);
                    newDatas.push(rootNode);
                    modelNameMap.set(key, modelInfo.name);
                    rootNodeMap.set(key, rootNode);
                } else {
                    var rootNode = rootNodeMap.get(key);
                    var childTitle= modelInfo.createTime;
                    if(modelInfo.type == "5"){
                        childTitle = modelInfo.modelId.split("_")[1];
                    }
                    var childNode = {
                        title: childTitle,
                        disableMenu: false,
                        libraryType: "modelLibray",
                        icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-unselect'
                    };
                    $.extend(childNode, modelInfo);
                    rootNode.children.push(childNode);
                }
            }
        }
        return {
            datas: newDatas,
            datasMap: cacheDataMap
        }
    }

    /**
     * 导入PMML模型
     */
    var importPMMLModel = function (el) {
        var isStop = false;
        var dialog = $("<div/>").appendTo($("body")).dialog({
            title: TempoUtils.locale("mine.pmmlmodelimport"),
            height: 170,
            width: 500,
            modal: true,
            draggable: true,
            resizable: false,
            buttons: [{
                text: TempoUtils.locale("mine.import"),
                click: function (e) {
                    if (isStop) return;
                    var form = dialog.find('form');
                    var nameshow = form.find('input[name=nameshow]')
                    var file = nameshow.val();
                    if (file) {
                        var process = $("<div/>").tempoprogressbar();
                        form.ajaxSubmit({
                            dataType: 'json',
                            type: 'post',
                            beforeSubmit: function (result) {
                                isStop = true;
                                return true;
                            },
                            success: function (data) {
                                if (data.status == "true") {
                                    Eventbus.trigger("loadMineModelLibrary.mine");
                                    $("<div/>").alert({
                                        msg: TempoUtils.locale("mine.importpmmlsuccess")
                                    })
                                } else {
                                    $("<div/>").alert({
                                        msg: TempoUtils.locale("mine.importpmmlfail") + data.message
                                    })
                                }
                            },
                            complete: function () {
                                dialog.dialog('destroy').remove();
                                process.tempoprogressbar('destroy');
                            },
                            error: function (e) {
                                process.tempoprogressbar("destroy");
                                TempoUtils.uploadErrorHandler(e);
                            }
                        });
                    } else {
                        nameshow.validatebox('doValidate');
                        nameshow.validatebox('showTip');
                    }
                }
            }],
            hide: {
                effect: 'fade',
                duration: 300
            },
            open: function () {
                var ui = $(this);
                var form = $('<form>').appendTo(ui)
                    .attr('enctype', 'multipart/form-data')
                    .attr('method', 'post')
                    .attr("action", contextPath + '/api/ai/mine/importPmmlModel');
                $('<input name="themeId" type="hidden">').appendTo(form).val(window[constant.ANALYSE_ID]);
                $('<label>').text(TempoUtils.locale("mine.pmmlmodel_file")).appendTo(form);
                var filenameText = $('<input name="nameshow">').appendTo(form)
                    .validatebox({
                        readonly: true,
                        width: 300,
                        height: 28,
                        required: true,
                        tip: TempoUtils.locale("mine.pmmlmodel_upload_tip")
                    })
                    .css('margin', '2px 10px 0px 10px');
                var wrapper = $('<a href="javascript:void(0)" >')
                    .appendTo(form)
                    .text(TempoUtils.locale("mine.pmmlfile_choose"))
                    .css({
                        'margin-bottom': '3px',
                        'overflow': 'hidden',
                        'cursor': 'pointer'
                    })
                    .button({
                        click: function (e) {
                        }
                    });
                var fileInput = $('<input class="uploadinput">')
                    .attr('type', 'file')
                    .attr('name', 'file')
                    .attr('accept', '.pmml')
                    .css({
                        opacity: 0,
                        position: 'absolute',
                        top: 0,
                        right: 0,
                        "font-size": '100px'
                    })
                    .appendTo(wrapper)
                    .unbind("click")
                    .bind("click", function (e) {
                        filenameText.val("");
                        fileInput.val("");
                    });
                fileInput.bind("change", function (e) {
                    var files = e.currentTarget.files;
                    if (!files || files.length == 0) {
                        return;
                    }
                    var acceptType = ["pmml", "xml"];
                    var fileSize = files[0].size;
                    if (fileSize && fileSize / 1024 / 1024 > 10) {
                        $("<div/>").alert({
                            msg: TempoUtils.locale("mine.importpmmlfail") + TempoUtils.locale("mine.pmmlfileSizeError")
                        })
                        return;
                    }
                    var fileName = files[0].name;
                    if (!fileName || acceptType.indexOf(fileName.substr(fileName.lastIndexOf(".") + 1).toLowerCase()) == -1) {
                        $("<div/>").alert({
                            msg: TempoUtils.locale("mine.importpmmlfail") + TempoUtils.locale("mine.pmmlfileTypeError")
                        })
                        return;
                    } else {
                        filenameText.validatebox('setValue', fileName)
                    }
                });
            },
            close: function () {
                $(this).dialog("destroy").remove();
            }
        });
    }

    /**
     * 初始化模型库
     */
    var initModelLibrary = function (isK8sCluster, isK8sLocal) {
        var container = $("#tempo-mine-library-manager-container");
        container.empty();
        $('<div id="tempo-mine-element-library"><div class="ui-layout-center"></div><div class="ui-layout-south"></div></div>').appendTo(container);
        var lbContainer = container.find('.ui-layout-center');
        lbContainer.css({"height": "85%"});
        var pagebarContainer = container.find('.ui-layout-south');
        pagebarContainer.css({"height": "10%"});
        var opts = {};
        if (isK8sCluster || isK8sLocal) {
            opts = {
                "all": TempoUtils.locale("mine.all"),
                "classification": TempoUtils.locale("mine.classification"),
                "regression": TempoUtils.locale("mine.regression"),
                "clustering": TempoUtils.locale("mine.clustering"),
                "association": TempoUtils.locale("mine.association"),
                "timeseries": TempoUtils.locale("mine.timeseries"),
                "comprehensiveevaluation": TempoUtils.locale("mine.comprehensiveevaluation"),
                "textmining": TempoUtils.locale("mine.textmining"),
                "recommendation": TempoUtils.locale("mine.recommendation"),
                "pmml": TempoUtils.locale("mine.pmml"),
                "other": TempoUtils.locale("mine.other")
            };
        } else {
            opts = {
                "all": TempoUtils.locale("mine.all"),
                "classification": TempoUtils.locale("mine.classification"),
                "regression": TempoUtils.locale("mine.regression"),
                "clustering": TempoUtils.locale("mine.clustering"),
                "association": TempoUtils.locale("mine.association"),
                "timeseries": TempoUtils.locale("mine.timeseries"),
                "comprehensiveevaluation": TempoUtils.locale("mine.comprehensiveevaluation"),
                "textmining": TempoUtils.locale("mine.textmining"),
                "recommendation": TempoUtils.locale("mine.recommendation"),
                "tensorflow": "Tensorflow",
                "pmml": TempoUtils.locale("mine.pmml"),
                "other": TempoUtils.locale("mine.other")
            };
        }
        if ($("#tempo-mine-pmml-model-option").length == 0) {
            delete opts['pmml'];
        }
        var selectContainer = $("<div/>").addClass("tempo-panel-title").css({
            "padding-left": "7px",
            "padding-bottom": "0px"
        }).appendTo(lbContainer);
        var searchContainer = $('<div/>').addClass('tempo-mine-model-search-container').css({"padding": "2px 0",})
            .appendTo(lbContainer);
        var searcher = $('<div>').addClass('tempo-mine-element-search').appendTo(searchContainer);
        searcher.searchbar({
            width: 216,
            auto: true,
            placeholder: TempoUtils.locale("mine.sousumoxingmingcheng"),
            leftsearchBtn: false,
            hasClean: true
        });
        searcher.css({'margin': '0 auto'});
        var selector = $('<select id="tempo-mine-alg-type-select"></select>').appendTo(selectContainer);
        $.each(opts, function (key, value) {
            var option = $("<option/>", {
                "value": key,
                "text": value
            }).appendTo(selector);
        });
        //获取当前流程的类型
        var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
        //初始化模型库下拉框
        selector.selectmenu({
            width: 180,
            open: function (e) {
                //获取当前流程的类型
                var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
                if (flowType == "plflow") {
                    //目前只支持分类，回归和其他，其余的后续扩展，不支持的类型隐藏
                    $(this).selectmenu("hideItems", TempoMineUtils.plFlowNoSupportModelType);
                }
            }
        });
        if ($("#tempo-mine-pmml-model-option").length > 0) {
            var pmmlModelOption = $('<span id="tempo-mine-pmml-model" class="ui-icon tempo-ui-icon tempo-mine-button tempo-mine-addpage-model" title="PMML模型导入"></span>')
                .appendTo(selectContainer);
            pmmlModelOption.unbind("click").bind("click", function () {
                Eventbus.trigger("importPMMLModel.mine");
            }).attr("title", TempoUtils.locale("mine.pmmlimport"));
        } else {
            selector.selectmenu({width: 216});
        }
        getListModelInfoLibrary(flowType);
        //有人修改了公共样式，需要在这里加一个背景颜色，修改52164bug
        container.find(".tempo-panel-title").css("background", "#EAEDF1");
    }

    /**
     * 获取模型库信息
     */
    var getListModelInfoLibrary = function (flowType) {
        var process = $("<div/>").tempoprogressbar();
        $.ajax({
            url: contextPath + '/api/ai/mineExecute/listModelInfoLibray',
            data: {
                analyseId: window[constant.ANALYSE_ID]
            },
            type: 'post',
            success: function (datas) {
                process.tempoprogressbar("destroy");
                //管道流程不支持高级特征提取生成的模型
                var newData;
                if ("plflow" == flowType) {
                    newData = TempoMineUtils.getListModelInfoLibraryOfPlFlow(datas);
                } else {
                    newData = datas;
                }
                var ret = processModelDatas(newData);
                $('#tempo-mine-element-library').modellibrary({
                    data: ret.datas,
                    cacheDataMap: ret.datasMap
                });
            }
        });
    }

    //准备要素库
    var prepareElementLibrary = function (isYarn, isK8sCluster, isOpenHadoop, isK8sLocal) {
        //常用操作
        var commonOperEles = window[window.constant.DATAMINE_COMMONOPER];
        //数据
        var dataEles = window[window.constant.DATAMINE_DATA];
        //处理
        var prepEles = window[window.constant.DATAMINE_PRE];
        //模型
        var modelEles = window[window.constant.DATAMINE_MODEL];
        //算法
        var algEles = window[window.constant.DATAMINE_TYP];

        var extendEles = window[window.constant.DATAMINE_EXTEND];
        //控制
        var controlEles = window[window.constant.DATAMINE_CONTROL];
        //图表
        var graphEles = window[window.constant.DATAMINE_CHART];
        //自定义
        var udEles = window[window.constant.USER_DEFINED];

        var funsionEles = window[window.constant.DATAMINE_FUNSION];

        var featureengEles = window[window.constant.DATAMINE_FEATUREENG];

        var deeplearningEles = window[window.constant.DATAMINE_DEEPLEARNING];

        var integratedlearningEles = window[window.constant.DATAMINE_INTEGRATED];

        var autoEles = window[window.constant.DATAMINE_AUTO];

        //var cfEles = window[window.constant.DATAMINE_CF];

        var statisticsEles = window[window.constant.DATAMINE_STATISTICS];

        var textMiningEles = window[window.constant.DATAMINE_TEXTMINING];

        //流处理
        //var streamEles = window[window.constant.DATAMINE_STREAM];
        //金融分析
        var financeEles = window[window.constant.DATAMINE_FINANCE];
        //信号处理
        var signalEles = window[window.constant.DATAMINE_SIGNAL];
        //查询需要显示的自定义算法节点
        var needShowNode = [];
        //查询需要显示的节点集合
        $.ajax({
            url: contextPath + "/api/ai/nodemgmt/list-visible-node",
            type: 'post',
            async: false,
            success: function (result) {
                needShowNode = result.data;
            }
        });
        var all = [];
        all.push({
            children: groupByCategory(commonOperEles, '', isYarn, true, needShowNode),
            title: TempoUtils.locale("mine.common_operators"),
            icon: 'tempo-ui-icon-mine-common-operators'
        });
        var bAi = !$.isEmptyObject(funsionEles) || !$.isEmptyObject(featureengEles) || !$.isEmptyObject(statisticsEles) || !$.isEmptyObject(deeplearningEles) || !$.isEmptyObject(autoEles) || !$.isEmptyObject(integratedlearningEles) || !$.isEmptyObject(autoEles) || !$.isEmptyObject(textMiningEles);
        if (bAi) {
            if (!$.isEmptyObject(dataEles)) {
                all.push({
                    children: groupByCategory(dataEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_data") + " (" + getCategoryNum(dataEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-dataset'
                });
            }

            if (!$.isEmptyObject(prepEles)) {
                all.push({
                    children: groupByCategory(prepEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_process") + " (" + getCategoryNum(prepEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-process'
                });
            }

            // if(!$.isEmptyObject(streamEles)) {
            // 	all.push({children: groupByCategory(streamEles, '', isYarn), title: TempoUtils.locale("mine.mine_stream")+" ("+getCategoryNum(streamEles,isYarn)+")", icon: 'tempo-ui-icon-dm-stream'});
            // }
            if (!$.isEmptyObject(funsionEles)) {
                all.push({
                    children: groupByCategory(funsionEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_fusion") + " (" + getCategoryNum(funsionEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-fusion'
                });
            }
            if (!$.isEmptyObject(featureengEles)) {
                all.push({
                    children: groupByCategory(featureengEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_featureeng") + " (" + getCategoryNum(featureengEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-featureeng'
                });
            }
            if (!$.isEmptyObject(statisticsEles)) {
                all.push({
                    children: groupByCategory(statisticsEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_statistics") + " (" + getCategoryNum(statisticsEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-statistics'
                });
            }
            if (!$.isEmptyObject(graphEles)) {
                all.push({
                    children: groupByCategory(graphEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_graphic") + " (" + getCategoryNum(graphEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'tempo-ui-icon-graph'
                });
            }
            if (!$.isEmptyObject(algEles)) {
                all.push({
                    children: groupByCategory(algEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_arithmetic") + " (" + getCategoryNum(algEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-algorithm'
                });
            }
            if (!$.isEmptyObject(deeplearningEles)) {
                all.push({
                    children: groupByCategory(deeplearningEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_deeplearing") + " (" + getCategoryNum(deeplearningEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-deeplearing'
                });
            }
            if (!$.isEmptyObject(integratedlearningEles)) {
                all.push({
                    children: groupByCategory(integratedlearningEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_integratedlearing") + " (" + getCategoryNum(integratedlearningEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-integratedlearing'
                });
            }
            if (!$.isEmptyObject(autoEles)) {
                all.push({
                    children: groupByCategory(autoEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_auto") + " (" + getCategoryNum(autoEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-auto'
                });
            }
            if (!$.isEmptyObject(extendEles)) {
                all.push({
                    children: groupByCategory(extendEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_extend") + " (" + getCategoryNum(extendEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-extend'
                });
            }
            if (!$.isEmptyObject(textMiningEles)) {
                all.push({
                    children: groupByCategory(textMiningEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_textmining") + " (" + getCategoryNum(textMiningEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-textmining'
                });
            }
            // if (!$.isEmptyObject(cfEles)) {
            // 	all.push({children: groupByCategory(cfEles, '', isYarn), title: TempoUtils.locale("mine.ai_cf")+" ("+getCategoryNum(cfEles,isYarn)+")", icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-cf'});
            // }
            if (!$.isEmptyObject(modelEles)) {
                if (window.isFlab != null) {
                    all.push({
                        children: groupByCategory(modelEles, '', isYarn),
                        title: TempoUtils.locale("mine.training_model") + " (" + getCategoryNum(modelEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                        icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-model'
                    });
                } else {
                    all.push({
                        children: groupByCategory(modelEles, '', isYarn),
                        title: TempoUtils.locale("mine.ai_modelmanager") + " (" + getCategoryNum(modelEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                        icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-model'
                    });
                }
            }

            if (!$.isEmptyObject(controlEles)) {
                all.push({
                    children: groupByCategory(controlEles, '', isYarn),
                    title: TempoUtils.locale("mine.ai_control") + " (" + getCategoryNum(controlEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-control'
                });
            }

            if (!$.isEmptyObject(financeEles)) {
                all.push({
                    children: groupByCategory(financeEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_finance") + " (" + getCategoryNum(financeEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-finance'
                });
            }
            if (!$.isEmptyObject(signalEles)) {
                all.push({
                    children: groupByCategory(signalEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_signal") + " (" + getCategoryNum(signalEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-signal'
                });
            }
        } else {
            if (!$.isEmptyObject(dataEles)) {
                all.push({
                    children: groupByCategory(dataEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_data") + " (" + getCategoryNum(dataEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-dataset'
                });
            }

            if (!$.isEmptyObject(prepEles)) {
                all.push({
                    children: groupByCategory(prepEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_process") + " (" + getCategoryNum(prepEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-process'
                });
            }

            // if(!$.isEmptyObject(streamEles)){
            // 	all.push({children: groupByCategory(streamEles, '', isYarn), title: TempoUtils.locale("mine.mine_stream")+" ("+getCategoryNum(streamEles,isYarn)+")", icon: 'tempo-ui-icon-dm-stream'});
            // }

            if (!$.isEmptyObject(algEles)) {
                all.push({
                    children: groupByCategory(algEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_arithmetic") + " (" + getCategoryNum(algEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-algorithm'
                });
            }
            if (!$.isEmptyObject(extendEles)) {
                all.push({
                    children: groupByCategory(extendEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_extend") + " (" + getCategoryNum(extendEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-extend'
                });
            }

            if (!$.isEmptyObject(algEles)) {
                all.push({
                    children: groupByCategory(modelEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_model") + " (" + getCategoryNum(modelEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-model'
                });
            }

            if (!$.isEmptyObject(graphEles)) {
                all.push({
                    children: groupByCategory(graphEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_graphic") + " (" + getCategoryNum(graphEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'tempo-ui-icon-graph'
                });
            }

            if (!$.isEmptyObject(controlEles)) {
                all.push({
                    children: groupByCategory(controlEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_control") + " (" + getCategoryNum(controlEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-control'
                });
            }

            if (!$.isEmptyObject(financeEles)) {
                all.push({
                    children: groupByCategory(financeEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_finance") + " (" + getCategoryNum(financeEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-finance'
                });
            }
            if (!$.isEmptyObject(signalEles)) {
                all.push({
                    children: groupByCategory(signalEles, '', isYarn),
                    title: TempoUtils.locale("mine.mine_signal") + " (" + getCategoryNum(signalEles, isYarn, isK8sCluster, isK8sLocal) + ")",
                    icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-signal'
                });

            }
        }

        if (!isK8sCluster && !isK8sLocal) {
            all.push({
                children: groupByCategory(udEles, '', isYarn, undefined, 'user_defined', needShowNode),
                title: TempoUtils.locale("mine.user_defined") + " (" + getUserCategoryNum(udEles, isYarn, needShowNode, isK8sCluster) + ")",
                icon: 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-defined'
            });
        }

        for (var i = 0; i < all.length; i++) {
            var title = all[i].title;
            if (!!title) {
                var num = title.substring(title.lastIndexOf("(") + 1, title.lastIndexOf(")"));
                if (String(num) === "0") {
                    all.splice(i, 1);
                    i--;
                }
            }
        }

        return all;
    }

    /**
     * 初始化要素库
     * @param data 要素库数据
     */
    var initLibrary = function (data) {
        var container = $("#tempo-mine-library-manager-container");
        container.empty();
        if (window.apiPreview) {
            container.hide();
        }
        $('<div id="tempo-mine-element-library"><div class="ui-layout-center"></div><div class="ui-layout-south"></div></div>').appendTo(container);

        $('#tempo-mine-element-library').elementlibrary({data: data});
        //获取当前流程的类型
        var flowType = Eventbus.triggerHandler("getFlowType.mine")[0];
        //如果当前选中的流程为管道流程则要重新渲染
        if (flowType && flowType == "plflow") {
            Eventbus.triggerHandler("mine.library-isDistribute", false, "", flowType);
        }
        if (window.apiDesigner) {
            $('.tempo-mine-library-personal-btn').remove();
            $(".distributeSwitch-div").css("padding-left", "0px");
        }
        Eventbus.one('clear_help_content.mine', function () {
            $('#tempo-mine-element-library').elementlibrary('clearHelp');
        })
    };

    var groupToChildren = function (eles, icon, isYarn) {
        var children = [];
        for (var e in eles) {
            var ele = eles[e];
            window[window.constant.MNODES][ele.id] = ele;
            ele.title = ele.name;
            var icon = 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-unselect';
            /*if(!TempoAuthorityUtils.isGrantedForMiningNode(ele.id)){
                ele.disableDrag = true;
                ele.disableMenu = true;
                icon = 'ui-icon tempo-icon-lock-black';
            }*/
            ele.icon = icon;
            children.push(ele);
        }
        children.sort(function (a, b) {
            return a.index - b.index;
        });
        return children;
    }

    //获取节点总数
    var getUserCategoryNum = function (eles, isYarn, needShowNode, isK8sCluster, isK8sLocal) {
        var elegroups = [];
        //分布式节点个数
        for (var p in eles) {
            var ele = eles[p];
            window[window.constant.MNODES][ele.id] = ele;
            //当节点的设置为隐藏时，则不显示节点，单是之前使用的流程可以继续使用
            if (String(ele.visible) === "false" || String(ele.isShow) === "false") continue;
            if (needShowNode != null && needShowNode.indexOf(p) === -1) continue;
            //节点所属于的特定环境，没有设置属性则使用嵌入和云两种模式
            if ((isYarn && ele.deployMode == 'process')
                || (!isYarn && ele.deployMode == 'yarn')) {
                if ((isK8sCluster || isK8sLocal) && ele.deployMode != undefined) {
                    elegroups.push(ele)
                }
                continue;
            } else {
                elegroups.push(ele);
            }
        }
        var length = elegroups.length
        return length;
    }

    //获取节点总数
    var getCategoryNum = function (eles, isYarn, isK8sCluster, isK8sLocal) {
        var elegroups = [];
        //分布式节点个数
        for (var p in eles) {
            var ele = eles[p];
            window[window.constant.MNODES][ele.id] = ele;
            //当节点的设置为隐藏时，则不显示节点，单是之前使用的流程可以继续使用
            if (String(ele.visible) === "false" || String(ele.isShow) === "false") continue;
            //节点所属于的特定环境，没有设置属性则使用嵌入和云两种模式
            if ((isYarn && ele.deployMode == 'process')
                || (!isYarn && ele.deployMode == 'yarn')) {
                if ((isK8sCluster || isK8sLocal) && ele.deployMode != undefined) {
                    elegroups.push(ele)
                }
                continue;
            } else {
                elegroups.push(ele);
            }
        }
        var length = elegroups.length
        return length;
    }

    //根据类型进行分组
    var groupByCategory = function (eles, icon, isYarn, isOperEles, type, needVisibleNode) {
        var categoryEles = {};
        var userdefinedEles = {};
        if ("user_defined" == type) {
            for (var p in eles) {
                var ele = eles[p];
                if (ele.category == 'user_defined') {//二级分类如果是user_defined，将该ele往前放
                    userdefinedEles[p] = ele;
                } else {
                    categoryEles[p] = ele;
                }
            }
            eles = {};
            $.extend(eles, userdefinedEles, categoryEles);
        }


        var groups = {};
        var style = $('<style/>').attr('type', 'text/css').attr('see', 'ming-modeling.js');
        //分布式节点个数
        for (var p in eles) {
            var ele = eles[p];
            window[window.constant.MNODES][ele.id] = ele;
            //当节点的设置为隐藏时，则不显示节点，单是之前使用的流程可以继续使用
            if (String(ele.visible) === "false" || String(ele.isShow) === "false") continue;
            if (needVisibleNode != null && needVisibleNode.indexOf(p) === -1) continue;
            //节点所属于的特定环境，没有设置属性则使用嵌入和云两种模式
            if ((isYarn && ele.deployMode == 'process')
                || (!isYarn && ele.deployMode == 'yarn')) {
                //continue;
            }
            // 自定义算法节点添加权限控制
            if (ele.type == 'user_defined' && window.userNodeAuth
                && window.userNodeAuth.auth) {
                var filter = window.userNodeAuth.nodes.filter(function (node) {
                    return ele.id == node.nodeId
                });
                if (filter.length == 0) {
                    delete window[window.constant.MNODES][ele.id];
                    if (window[window.constant.USER_DEFINED]) {
                        delete window[window.constant.USER_DEFINED][ele.id]
                    }
                    continue;
                }
                var node = filter[0];
                ele.description = node.remark;
            }
            if (!!!groups[ele.category]) {
                if (isOperEles) {
                    if (!!!groups[ele.undefined]) {
                        groups[ele.undefined] = {
                            title: TempoUtils.locale('mine.' + ele.undefined),
                            category: ele.undefined,
                            index: window.mineConstant.ELEMENT_LIBRARY[ele.undefined],
                            children: []
                        };
                    }
                } else {
                    if (ele.type == 'user_defined') {
                        if (ele.category == 'user_defined') {
                            ele.categoryName = undefined;
                        }
                        groups[ele.category] = {
                            title: ele.categoryName,
                            category: ele.category,
                            index: window.mineConstant.ELEMENT_LIBRARY[ele.category],
                            children: []
                        };
                    } else {
                        // 如果是层级
                        groups[ele.category] = {
                            title: TempoUtils.locale('mine.' + ele.category),
                            category: ele.category,
                            index: window.mineConstant.ELEMENT_LIBRARY[ele.category],
                            children: []
                        };
                    }
                }
            }
            ele.title = ele.name;
            var icon = 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-unselect';
            //挖掘节点没有授权时，在节点前加锁。并且不能拖动。
            /*if(!TempoAuthorityUtils.isGrantedForMiningNode(ele.id)
                    && ele.type != 'user_defined'){
                ele.disableDrag = true;
                ele.disableMenu = true;
                icon = 'ui-icon tempo-icon-lock-black';
            }*/
            ele.icon = icon;
            if (ele.libraryIcon) {
                ele.icon += " tempo-mine-library-node-" + ele.id;
                var css = style.html()
                    + "\n .tempo-mine-library-node-" + ele.id + "{"
                    + " background-image: url(\"" + contextPath + "" + ele.libraryIcon + "\"); "
                    + " background-position: 0 5px;"
                    + "} ";
                style.html(css);
            }
            var group = {};
            if (isOperEles) {
                group = groups[ele.undefined];
            } else {
                group = groups[ele.category];
            }
            if (!!ele.order) group.children.splice(Number(ele.order), 0, ele);
            else group.children.push(ele);
        }
        //动态添加要素库图标的样式
        $('head').append(style);
        var gp = [];
        // 对自定义算法进行特殊操作，将二级节点放出来
        var userdefinedNode = [];
        if (groups['user_defined']) {
            userdefinedNode = TempoUtils.clone(groups['user_defined'].children);
            delete groups['user_defined'];
        }
        for (var g in groups) {
            var e = groups[g];
            e.groupType = g;
            e.type = 'group';
            e.icon = 'ui-icon tempo-ui-icon tempo-ui-icon-no-mutual tempo-ui-icon-library-close';
            if (e.title != null) {
                e.title = e.title + " (" + e.children.length + ")";
            }
            gp.push(e);
        }
        gp.sort(function (a, b) {
            return a.index - b.index;
        });
        if (!isOperEles) {
            gp.forEach(function (item) {
                if (item.children && item.children instanceof Array) {
                    item.children.sort(function (a, b) {
                        return a.index - b.index;
                    })
                }
            });
        }
        if (userdefinedNode.length != 0) {
            for (var i=userdefinedNode.length -1; i>=0; i--) {
                gp.unshift(userdefinedNode[i]);
            }
        }
        return gp;
    };

    /**
     * 获取当前页面流程类型
     * @returns {*|jQuery}
     */
    var getFlowType = function () {
        //获取当前选择流程的类型
        var modelTabs = $('#tempo-mine-model-tabs');
        var modelTabContParent = modelTabs.find('.tempo-mine-cont');
        var curSelectSpan = modelTabContParent.find(".tempo-mine-tab-curSelect");
        var flowType = $(curSelectSpan).find("img[class='tempo-mine-flow-image-icon']").attr("flowType");
        return flowType;
    }

    !function () {
        //设计端启用限制，不能新增流程
        if (TempoAuthorityUtils.isDesignerLimited()) {
            addPageBtn.remove();
            addPagePLBtn.remove();
        }
        if (window.apiPreview) {
            addPageBtn.remove();
            addPagePLBtn.remove();
        } else {
            // 编辑模式页签显示菜单
            tabContainer.addClass('tempo-mine-tab-editable');
        }
        Eventbus.one('model&viewChanged.mine', function () {
            resizeSheetPager();
            rollpage.roll();
            rollpage.resize();
        });
        Eventbus.one('updatePageName.mine', updatePageName);
        //初始化获取当前页面流程类型方法
        Eventbus.one('getFlowType.mine', getFlowType);
        loadElementLibrary(function () {
            Eventbus.one("mining_board_change.mine", addChangeMarkToModelTabCont);
            Eventbus.one("mining_board_save.mine", removeChangeMark);
            if (window.apiDesigner) {
                // pagerClick(null, true, window.id);
                $('.tempo-mine-library-personal-btn').remove();
                $(".distributeSwitch").css("margin-left", "0px");
            } else {

            }
            // 在页面中先隐藏，在代码中显示，优化加载时页面显示
            modelTabs.show();
            loadAnalyseThemeAll();
        });
        //body添加点击事件，来判断是否为选中节点，否则清除选中状态
        $('body').off('click.modeling').on('click.modeling', function (e, data) {
            // if($(e.target).closest(".tempo-mine-board").length == 0) {
            if (data != 'miningnode') {
                var analyseStatus = Eventbus.triggerHandler("getAnalyseStatus")[0];
                var curMainId = analyseStatus.getMainId();
                var page = analyseStatus.getFlowPanel(curMainId);
                if (page) {
                    var board = page.panel.flowpanel('getBoard');
                    //如果鼠标再面板中发生移动了，则取消后续操作
                    try {
                        if (board.data("tempo-miningboard") && board.miningboard("getSelectStatus")) {
                            board.miningboard("setSelectStatus", false);

                            //获取鼠标当前的位置
                            var mouseX = e.clientX, mouseY = e.clientY;
                            //获取区域的位置
                            var boardRect = board.parent()[0].getBoundingClientRect();
                            var boardMinX = boardRect.left, boardMaxX = boardRect.left + boardRect.width - 10;
                            var boardMinY = boardRect.top, boardMaxY = boardRect.top + boardRect.height - 10;
                            if (!(mouseX >= boardMinX && mouseX <= boardMaxX && mouseY >= boardMinY && mouseY <= boardMaxY)) {
                                $(".tempo-miningboard-frame-selection").remove();
                                board.off(".selectAllNode");
                                //修改鼠标样式
                                board.parent().css("cursor", "");
                                board.css("cursor", "");
                                board.children().css("cursor", "");
                            }
                            return;
                        }
                    } catch (e) {
                    }
                    var name = board.attr('_widgetname');
                    if (name) board[name]('clearSelect');
                }
            }
            //}
        });
    }();
}

window.MineModelingController = MineModelingController;